package cn.edu.zzuli.nothinglink.config;

import cn.edu.zzuli.nothinglink.config.realm.StudentRealm;
import cn.edu.zzuli.nothinglink.config.realm.TeacherRealm;
import cn.edu.zzuli.nothinglink.handler.JWTHandler;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.*;

@Configuration
public class ShiroConfig {

    //ShiroFilterFactoryBean
    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //配置jwt token
        Map<String, Filter> filters = new HashMap<>();
        filters.put("jwt",new JWTHandler());
        shiroFilterFactoryBean.setFilters(filters);

        //拦截器Map的创建
        Map<String, String> map = new LinkedHashMap<>();
        //针对不同的url，使用不同的拦截器，放到map中，即可生效，完成拦截
        //拦截所有请求
//        map.put("/*", "authc");
        //放行登陆请求
        map.put("/", "anon");
        //放行登录认证请求
        map.put("/stu/login", "anon");
        map.put("/stu/register", "anon");
        map.put("/tea/login", "anon");
        map.put("/tea/register", "anon");


//        map.put("/**", "jwt");
        //设置拦截成功以后，访问的页面
        shiroFilterFactoryBean.setLoginUrl("/");
        //设置相关的map集合，完成拦截功能的收集
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    //DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(
            @Qualifier("studentRealm") StudentRealm studentRealm,
            @Qualifier("teacherRealm") TeacherRealm teacherRealm) {
        //创建管理类
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        List<Realm> realms = new ArrayList<>();
        realms.add(studentRealm);
        realms.add(teacherRealm);

        //关联realm,可以设置多个realm
        //securityManager.setRealm(studentRealm);
        securityManager.setRealms(realms);

        //关闭shiro自带的session
        DefaultSubjectDAO subjectDAO=new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator=new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        return securityManager;
    }

    /**
     * 系统自带的Realm管理，主要针对多realm
     * */
    @Bean
    public ModularRealmAuthenticator modularRealmAuthenticator() {
        ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
        //只要有一个成功就视为登录成功
        modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        return modularRealmAuthenticator;
    }


    //Realm
    @Bean(name = "studentRealm")
    public StudentRealm userRealm() {
        return new StudentRealm();
    }

    @Bean(name = "teacherRealm")
    public TeacherRealm teacherRealm(){
        return new TeacherRealm();
    }


    /**
     * Shiro生命周期处理器
     * 要加入注解，指定方法的拦截，则需要加入以下的三个方法，开启注解模式
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * @return
     */
    @Bean
    @DependsOn({ "lifecycleBeanPostProcessor" })
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}
